#include "GfxDriver/WGL/WGLCubeTexture.h"

#include "GfxDriver/WGL/WGLHelper.h"

#include "GfxDriver/GfxDriver.h"
#include "Core/LogService.h"

namespace Orca {

	//--------------------------------------------------------------------------
	WGLCubeTexture* WGLCubeTexture::create(
		  GfxDriver *gfxDriver
		, uint32 size
		, PixelFormat format) {

		gfxDriver->resetErrors();

		GLuint glHandle;
		glGenTextures(1, &glHandle);
		
		WGLCubeTexture *tex = new WGLCubeTexture(gfxDriver, size, format, glHandle);

		LOG_MSG(
			"WGLGfxDriver: TextrueCube " + 
			toStr(size) + "  " +
			"glHandle=" + toStr((uint32)glHandle) );

		return tex;
	}

	//--------------------------------------------------------------------------
	WGLCubeTexture::WGLCubeTexture(
		  GfxDriver *gfxDriver
		, uint32 size
		, PixelFormat format
		, GLuint glHandle)
		
		: mGfxDriver(gfxDriver)
		, mSize(size)
		, mFmt(format)
		, mData(NULL)
		, mGLHandle(glHandle)
		, mCurrSide(CUBE_NONE) {

		// init gl texture settings
		glBindTexture(GL_TEXTURE_CUBE_MAP, glHandle);

		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
	}
	
	//--------------------------------------------------------------------------
	WGLCubeTexture::~WGLCubeTexture() {

		glDeleteTextures(1, &mGLHandle);

		if(mData)
			delete[] mData;
	}

	//--------------------------------------------------------------------------
	uint32 WGLCubeTexture::getSize() const {
		return mSize;
	}

	//--------------------------------------------------------------------------
	PixelFormat WGLCubeTexture::getPixelFormat() const {
		return mFmt;
	}

	//--------------------------------------------------------------------------
	void* WGLCubeTexture::requestUpload(CubeMapSide side) {

		if(CUBE_NONE == side)
			return NULL;

		if(!mData)
			mData = new uint8[mSize * mSize * WGLHelper::getBytePerPixel(mFmt)];

		mCurrSide = side;

		return mData;
	}
	
	//--------------------------------------------------------------------------
	bool WGLCubeTexture::uploadToGPU(bool autoGenMipmap) {

		if(CUBE_NONE == mCurrSide)
			return false;

		glBindTexture( GL_TEXTURE_CUBE_MAP, mGLHandle );
		
		if(autoGenMipmap)
			glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP, GL_TRUE);
		else
			glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP, GL_FALSE);

		GLint internalFmt;
		GLenum srcFmt, srcType;
		WGLHelper::getGLPixelFormat(mFmt, internalFmt, srcFmt, srcType);

		glTexImage2D(
			GL_TEXTURE_CUBE_MAP_POSITIVE_X + mCurrSide,
			0,
			internalFmt,
			(GLsizei)mSize,
			(GLsizei)mSize,
			0,
			srcFmt,
			srcType,
			mData);

		mCurrSide = CUBE_NONE;

		GLenum err = glGetError();

		if(err != GL_NO_ERROR) {

			return false;
		}

		delete[] mData;
		mData = NULL;

		glBindTexture( GL_TEXTURE_CUBE_MAP, 0 );

		return true;
	}

	//--------------------------------------------------------------------------
	unsigned int WGLCubeTexture::getAPIHandle() const {
		return mGLHandle;
	}

	//--------------------------------------------------------------------------
	unsigned int WGLCubeTexture::getAPITexType() const {
		return GL_TEXTURE_CUBE_MAP;
	}

	//--------------------------------------------------------------------------

}